package biz.datalk.industrialland.admin.modules.system.service.impl;

import biz.datalk.commons.utils.BasicParserUtils;
import biz.datalk.commons.utils.encryption.Des3Utils;
import biz.datalk.industrialland.admin.component.shiro.CustomLoginUser;
import biz.datalk.industrialland.admin.modules.system.mapper.ISysUserExtMapper;
import biz.datalk.industrialland.admin.modules.system.pojo.dto.SysUserDTO;
import biz.datalk.industrialland.admin.modules.system.pojo.vo.SysUserVO;
import biz.datalk.industrialland.admin.modules.system.service.ISysUserService;
import biz.datalk.industrialland.admin.modules.util.ShiroUtil;
import biz.datalk.industrialland.common.def.enums.DBYNEnum;
import biz.datalk.industrialland.common.exception.ServiceException;
import biz.datalk.industrialland.common.exception.ValidateException;
import biz.datalk.industrialland.common.result.UnifyResult;
import biz.datalk.industrialland.common.util.EntityIdUtils;
import biz.datalk.industrialland.common.util.I18NUtil;
import biz.datalk.industrialland.mbg.mapper.SysUserDepartMapper;
import biz.datalk.industrialland.mbg.mapper.SysUserMapper;
import biz.datalk.industrialland.mbg.mapper.SysUserRoleMapper;
import biz.datalk.industrialland.mbg.pojo.po.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author tarofang@163.com
 * @date 2019年08月12日
 */
@Slf4j
@Service
public class SysUserServiceImpl implements ISysUserService {

    private final SysUserMapper userMapper;

    private final ISysUserExtMapper userExtMapper;

    private final SysUserRoleMapper userRoleMapper;

    private final SysUserDepartMapper userDepartMapper;

    @Autowired
    public SysUserServiceImpl(
            SysUserMapper userMapper, //
            ISysUserExtMapper userExtMapper, //
            SysUserRoleMapper userRoleMapper, //
            SysUserDepartMapper userDepartMapper) {
        this.userMapper = userMapper;
        this.userExtMapper = userExtMapper;
        this.userRoleMapper = userRoleMapper;
        this.userDepartMapper = userDepartMapper;
    }

    @Override
    public UnifyResult list(SysUserDTO sysUserDTO) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc(SysUser.COL_UPDATE_TIME);
        queryWrapper.eq(SysUser.COL_IS_DELETE, DBYNEnum.N.name());
        String username = sysUserDTO.getUsername();
        queryWrapper.like(StringUtils.isNotBlank(username), SysUser.COL_USERNAME, StringUtils.trim(username));
        String realname = sysUserDTO.getRealname();
        queryWrapper.like(StringUtils.isNotBlank(realname), SysUser.COL_REALNAME, StringUtils.trim(realname));
        // 状态(1：正常  2：冻结 ）
        int status = BasicParserUtils.integerToInt(sysUserDTO.getStatus(), -1);
        queryWrapper.eq(status == 1 || status == 2, SysUser.COL_STATUS, status);
        // 性别（0：未指定 1：男 2：女）
        int sex = BasicParserUtils.integerToInt(sysUserDTO.getSex(), -1);
        queryWrapper.eq(sex == 0 || sex == 1 || sex == 2, SysUser.COL_SEX, sex);
        String email = sysUserDTO.getEmail();
        queryWrapper.like(StringUtils.isNotBlank(email), SysUser.COL_EMAIL, StringUtils.trim(email));
        String phone = sysUserDTO.getPhone();
        queryWrapper.like(StringUtils.isNotBlank(phone), SysUser.COL_PHONE, StringUtils.trim(phone));

        IPage<SysUser> page = new Page<>(sysUserDTO.getPageNumber(), sysUserDTO.getPageSize());
        IPage<SysUser> pageInfo = userMapper.selectPage(page, queryWrapper);

        return UnifyResult.success().mapData().put("rows", pageInfo.getRecords()).put("total", pageInfo.getTotal());

    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public UnifyResult addUser(SysUserDTO sysUserDTO) {
        // 判定 username 是否重复
        String username = sysUserDTO.getUsername().trim();
        SysUser exists = getUserByName(username);
        if (exists != null) {
            return UnifyResult.fail(I18NUtil.getMsg("user.username.exists"));
        }

        // 校验密码是否相同
        String password = sysUserDTO.getPassword().trim();
        String cipherPwd = Des3Utils.encode(password);

        String confPwd = StringUtils.trim(sysUserDTO.getConfPwd());
        if (!StringUtils.equals(password, confPwd)) {
            return UnifyResult.fail(I18NUtil.getMsg("user.pwd.disaffinity"));
        }

        CustomLoginUser customLoginUser = ShiroUtil.currentLoginUser();
        Date now = new Date();
        SysUser sysUser = new SysUser();
        sysUser.setUsername(username);
        sysUser.setPassword(cipherPwd);
        sysUser.setRealname(sysUserDTO.getRealname());
        // sysUser.setSalt(StringUtils.trimToEmpty(sysUserDTO.getSalt()));
        // sysUser.setAvatar(StringUtils.trimToEmpty(sysUserDTO.getAvatar()));
        sysUser.setBirthday(sysUserDTO.getBirthday());
        sysUser.setSex(sysUserDTO.getSex());
        sysUser.setEmail(StringUtils.trimToEmpty(sysUserDTO.getEmail()));
        sysUser.setPhone(StringUtils.trimToEmpty(sysUserDTO.getPhone()));
        // sysUser.setSysOrgCode(StringUtils.trimToEmpty(sysUserDTO.getSysOrgCode()));
        sysUser.setStatus(sysUserDTO.getStatus());
        // sysUser.setIsDelete(StringUtils.trimToNull(sysUserDTO.getIsDelete()));
        sysUser.setIsDelete(DBYNEnum.N.name());
        sysUser.setCreateBy(customLoginUser.getId());
        sysUser.setCreateName(customLoginUser.getRealname());
        sysUser.setCreateTime(now);
        sysUser.setUpdateBy(0L);
        sysUser.setUpdateName(StringUtils.EMPTY);
        sysUser.setUpdateTime(now);
        userMapper.insertSelective(sysUser);

        Long sysuserid = sysUser.getId();

        // 用户角色
        List<SysUserRole> userRoles = checkUserRoles(sysUserDTO, sysuserid);

        // 用户部门
        List<SysUserDepart> userDeparts = checkUserDeparts(sysUserDTO, sysuserid);

        for (SysUserRole userRole : userRoles) {
            userRoleMapper.insertSelective(userRole);
        }

        for (SysUserDepart userDepart : userDeparts) {
            userDepartMapper.insertSelective(userDepart);
        }

        return UnifyResult.success().setData(sysuserid);
    }

    private List<SysUserRole> checkUserRoles(SysUserDTO sysUserDTO, Long userid) {
        String sysroleids = sysUserDTO.getSysroleids();
        List<Long> roleids = EntityIdUtils.parseIds(sysroleids);

        List<SysUserRole> userRoles = new ArrayList<>();
        for (Long roleid : roleids) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userid);
            sysUserRole.setRoleId(roleid);
            userRoles.add(sysUserRole);
        }

        // if (roleids.size() != userRoles.size()) {
        //     throw new ValidateException(I18NUtil.getMsg("user.roles.invalid"));
        // }
        return userRoles;
    }

    private List<SysUserDepart> checkUserDeparts(SysUserDTO sysUserDTO, Long userid) {
        String sysorgids = sysUserDTO.getSysorgids();
        List<Long> orgids = EntityIdUtils.parseIds(sysorgids);

        List<SysUserDepart> userDeparts = new ArrayList<>();
        for (Long orgid : orgids) {
            SysUserDepart sysUserDepart = new SysUserDepart();
            sysUserDepart.setUserId(userid);
            sysUserDepart.setDepartId(orgid);

            userDeparts.add(sysUserDepart);
        }
        // if (orgids.length != userDeparts.size()) {
        //     throw new ValidateException(I18NUtil.getMsg("user.orgs.invalid"));
        // }
        return userDeparts;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public UnifyResult updateUser(SysUserDTO sysUserDTO) {
        SysUser exists = userMapper.selectById(sysUserDTO.getId());
        if (exists == null) {
            log.warn("Invalid id. [id={}]", sysUserDTO.getId());
            return UnifyResult.fail(I18NUtil.getMsg("user.no.exists.or.delete"));
        }

        // 用户名不能变更
        String username = sysUserDTO.getUsername();
        if (!username.equals(exists.getUsername())) {
            return UnifyResult.fail(I18NUtil.getMsg("user.update.username.change"));
        }

        // 只拷贝需要修改的属性
        /*
        try {
            MyBeanUtils.copyBeanNotNull2Bean(sysUserDTO, exists);
        } catch (Exception ex) {
            throw new ServiceException(ex.getMessage());
        }
        */

        String newRealname = sysUserDTO.getRealname();
        String newAvatar = sysUserDTO.getAvatar();
        Date newBirthday = sysUserDTO.getBirthday();
        Integer newSex = sysUserDTO.getSex();
        String newEmail = sysUserDTO.getEmail();
        String newPhone = sysUserDTO.getPhone();

        // 此处只会校验相关数据是否存在，不会校验其格式，请在前端自行完成校验
        // 用户的一部分属性只允许修改，不允许置空
        if (StringUtils.isNotBlank(newRealname)) {
            exists.setRealname(newRealname);
        }
        if (StringUtils.isNotBlank(newAvatar)) {
            exists.setAvatar(newAvatar);
        }
        if (newSex != null) {
            exists.setSex(newSex);
        }
        exists.setBirthday(newBirthday);
        exists.setEmail(StringUtils.trimToNull(newEmail));
        exists.setPhone(StringUtils.trimToNull(newPhone));
        exists.setSysOrgCode(sysUserDTO.getSysOrgCode());
        CustomLoginUser customLoginUser = ShiroUtil.currentLoginUser();
        Date now = new Date();
        exists.setUpdateBy(customLoginUser.getId());
        exists.setUpdateName(customLoginUser.getRealname());
        exists.setUpdateTime(now);

        // 用户角色
        Long sysuserid = exists.getId();
        List<SysUserRole> userRoles = checkUserRoles(sysUserDTO, sysuserid);

        // 用户部门
        List<SysUserDepart> userDeparts = checkUserDeparts(sysUserDTO, sysuserid);

        deleteUserRoleBySysUserid(sysuserid);
        deleteUserDepartBySysUserid(sysuserid);

        for (SysUserRole userRole : userRoles) {
            userRoleMapper.insertSelective(userRole);
        }

        for (SysUserDepart userDepart : userDeparts) {
            userDepartMapper.insertSelective(userDepart);
        }

        userMapper.updateByPrimaryKeySelective(exists);

        return UnifyResult.success();
    }

    @Override
    public void changeStatus(SysUserDTO sysUserDTO) {
        Long id = sysUserDTO.getId();
        if (id == null || id <= 0L) {
            throw new ValidateException("变更的数据不存在或已被删除");
        }

        // 状态(1：正常  2：冻结 ）
        int status = BasicParserUtils.integerToInt(sysUserDTO.getStatus(), -1);
        if (status != 1 && status != 2) {
            throw new ValidateException("未知的变更状态");
        }

        SysUser exists = userMapper.selectById(id);
        if (exists == null) {
            throw new ServiceException("变更的数据不存在或已被删除");
        }

        // 获取当前登录账号， 若变更账号为当前登录账号，无法变更为冻结状态
        SysUser currentUser = ShiroUtil.currentLoginUser().getSysUser();
        if (Objects.equals(currentUser.getId(), id) && status == 2) {
            throw new ServiceException("不能冻结当前登录账号");
        }

        SysUser param = new SysUser();
        param.setId(id);
        param.setStatus(status);
        CustomLoginUser customLoginUser = ShiroUtil.currentLoginUser();
        Date now = new Date();
        param.setUpdateBy(customLoginUser.getId());
        param.setUpdateName(customLoginUser.getRealname());
        param.setUpdateTime(now);

        userMapper.updateByPrimaryKeySelective(param);
    }

    @Override
    public SysUserVO detailById(Long id) {
        SysUser user = userMapper.selectById(id);
        if (user == null) {
            throw new ServiceException(I18NUtil.getMsg("user.no.exists.or.delete"));
        }

        SysUserVO sysUserVO = new SysUserVO();
        BeanUtils.copyProperties(user, sysUserVO);

        // 获取用户的部门
        List<SysDepart> orgs = getUserDepartBySysUserid(user.getId());
        sysUserVO.setUserDeparts(orgs);

        // 获取用户的角色
        List<SysRole> roles = getUserRoleBySysUserid(user.getId());
        sysUserVO.setUserRoles(roles);

        return sysUserVO;
    }

    @Override
    public List<SysRole> getUserRoleBySysUserid(Long sysuserid) {
        List<SysRole> roles = userExtMapper.getUserRoleBySysUserid(sysuserid);
        return CollectionUtils.isNotEmpty(roles) ? roles : new ArrayList<>();
    }

    @Override
    public List<SysDepart> getUserDepartBySysUserid(Long sysuserid) {
        List<SysDepart> roles = userExtMapper.getUserDepartBySysUserid(sysuserid);
        return CollectionUtils.isNotEmpty(roles) ? roles : new ArrayList<>();
    }

    @Override
    public int deleteUserRoleBySysUserid(Long sysuserid) {
        Integer resInt = userExtMapper.deleteUserRoleBySysUserid(sysuserid);
        return resInt == null ? 0 : resInt;
    }

    @Override
    public int deleteUserDepartBySysUserid(Long sysuserid) {
        Integer resInt = userExtMapper.deleteUserDepartBySysUserid(sysuserid);
        return resInt == null ? 0 : resInt;
    }

    @Override
    public int deleteById(Long id) {
        SysUser param = new SysUser();
        param.setId(id);
        param.setIsDelete(DBYNEnum.Y.name());
        int resInt = userMapper.updateByPrimaryKeySelective(param);
        return resInt;
    }

    @Override
    public void changePwd(SysUserDTO sysUserDTO) {
        Long id = sysUserDTO.getId();
        if (id == null || id <= 0L) {
            throw new ValidateException("变更的数据不存在或已被删除");
        }

        SysUser exists = userMapper.selectById(id);
        if (exists == null) {
            throw new ValidateException("变更的数据不存在或已被删除");
        }

        String pwd = StringUtils.trimToEmpty(sysUserDTO.getPassword());
        String confPwd = StringUtils.trimToEmpty(sysUserDTO.getConfPwd());
        if (StringUtils.isAnyEmpty(pwd, confPwd) || !StringUtils.equals(pwd, confPwd)) {
            throw new ValidateException("输入的密码不一致");
        }

        // String currentUserId = JwtUtil.getCurrentUserId();

        String cipherPwd = Des3Utils.encode(pwd);

        SysUser param = new SysUser();
        param.setId(id);
        param.setPassword(cipherPwd);
        CustomLoginUser customLoginUser = ShiroUtil.currentLoginUser();
        Date now = new Date();
        param.setUpdateBy(customLoginUser.getId());
        param.setUpdateName(customLoginUser.getRealname());
        param.setUpdateTime(now);

        userMapper.updateByPrimaryKeySelective(param);
    }

    @Override
    public SysUser getUserByName(String username) {
        return userExtMapper.getUserByName(username);
    }
}
